package vip.zhenzicheng.test.juc.atomic;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 手写自旋锁demo
 *
 * @author zhenzicheng
 * @date 2022-09-06 10:16
 * @see sun.misc.Unsafe
 */
@Slf4j
public class SpinLockCase {

  AtomicReference<Thread> atomicReference = new AtomicReference<>();

  public static void main(String[] args) {
    SpinLockCase spinLockCase = new SpinLockCase();

    new Thread(() -> {
      spinLockCase.lock();
      try {
        TimeUnit.SECONDS.sleep(3);
      } catch (InterruptedException e) {
        e.printStackTrace();
      } finally {
        spinLockCase.unlock();
      }
    }, "A").start();

    // A先于B启动
    try {
      TimeUnit.MILLISECONDS.sleep(500);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    new Thread(() -> {
      spinLockCase.lock();
      spinLockCase.unlock();
    }, "B").start();
  }

  public void lock() {
    Thread thread = Thread.currentThread();
    log.info(Thread.currentThread().getName() + "\t ----come in");
    // 如果没有线程存在，则存入当前线程
    while (!atomicReference.compareAndSet(null, thread)) {
      // 自旋中
    }
  }

  public void unlock() {
    Thread thread = Thread.currentThread();
    atomicReference.compareAndSet(thread, null);
    log.info(Thread.currentThread().getName() + "\t ----task over,unlock...");
  }
}
